#pragma once 
#include<pthread.h>
#include<iostream>
#include<queue>

#define NUM 10

template<class T>
class ThreadPool
{
private:
    int _num;//线程数量
    std::queue<T> task_queue;//任务阻塞队列->临界资源
    //线程同步与互斥
    pthread_mutex_t _lock;
    pthread_cond_t _cond;
public:
    //封装接口便于传入的对象调用
    void Lock()
    {
        pthread_mutex_lock(&_lock);
    }
    void UnLock()
    {
        pthread_mutex_unlock(&_lock);
    }
    void CondWait()
    {
        pthread_cond_wait(&_cond,&_lock);
    }
    void CondWake()
    {
        pthread_cond_signal(&_cond);

    }
    bool IsEmpty()
    {
        return task_queue.size()==0;
    }
public:
    ThreadPool(int num):_num(num)
    {
        pthread_mutex_init(&_lock,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }
    void InitThreadPool()
    {
        
        pthread_t tid;
        for(int i=0;i < _num;i++)//创建一批线程
        {
            pthread_create(&tid,nullptr,Routine,this);//传入线程池地址
            pthread_detach(tid);//线程分离
        }
    }
    //线程执行例程
    static void* Routine(void* arg)
    {
        ThreadPool* tp=(ThreadPool*)arg;
        //检测是否有任务-没任务等待；有任务进行获取并执行
        while(true)
        {
            //检查
            while(tp->IsEmpty())
                tp->CondWait();
            //取出任务
            T task;
            tp->Get(&task);
            task();//执行逻辑-仿函数
        }
    }
    void Put(const T& t)
    {
        Lock();
        task_queue.push(t);
        CondWake();//有任务进行唤醒
        UnLock();
    }
    void Get(T* t)
    {
        //取任务已经是获取到锁资源了
        *t=task_queue.front();
        task_queue.pop();
    }
};
